package com.markyao.es.repository;

import com.alibaba.fastjson.JSON;
import com.markyao.es.Article_model_es;
import com.markyao.es.EsResult;
import com.markyao.vo.Result;
import com.markyao.vo.parmas.EsParams;
import org.apache.http.HttpHost;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestionBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.python.antlr.ast.Str;
import org.springframework.stereotype.Repository;

import java.io.IOException;
import java.util.*;

@Repository
public class ArticleEsRepositoryImpl implements ArticleEsRepository{

    //创建es连接
    public ArticleEsRepositoryImpl() {
        makeConnection();
    }

    private static RestHighLevelClient client = null;

    //单例模式连接
    private static synchronized RestHighLevelClient makeConnection() {
        final BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider();
        //basicCredentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "password"));

        if (client == null) {
            client = new RestHighLevelClient(
                    RestClient.builder(new HttpHost("localhost", 9200, "http"))
                            .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                                @Override
                                public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                                    httpClientBuilder.disableAuthCaching();
                                    return httpClientBuilder.setDefaultCredentialsProvider(basicCredentialsProvider);
                                }
                            })
            );
        }

        return client;
    }

    //TODO: 关闭连接
    private static synchronized void closeConnection() throws IOException {
        client.close();
        client = null;
    }


    @Override
    public EsResult findAllEmployeeDetailsFromES(int currentPage) {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("blog_article");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.from(currentPage*5).query(QueryBuilders.matchAllQuery()).size(5);
        searchRequest.source(searchSourceBuilder);
        List<Article_model_es> list = new ArrayList<>();
        SearchResponse searchResponse = null;
        EsResult esResult=new EsResult();
        try {
            searchResponse =client.search(searchRequest, RequestOptions.DEFAULT);
            long length = searchResponse.getHits().getTotalHits().value;
            esResult.setTotalSize((int) length);
            if (length > 0) {
                SearchHit[] searchHit = searchResponse.getHits().getHits();
                for (SearchHit hit : searchHit) {
                    String sourceAsString = hit.getSourceAsString();
                    Article_model_es article_model_es = JSON.parseObject(sourceAsString, Article_model_es.class);
                    String content = article_model_es.getContent();
                    if (content!=null&&content.length()>256){
                        content=content.substring(0,256);
                    }
                    article_model_es.setContent(content);
                    list.add(article_model_es);
                }
            }
            esResult.setList(list);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return esResult;
    }


    @Override
    public EsResult findByFuzziness(EsParams esParams) {
        EsResult esResult=new EsResult();
        String queryStr = esParams.getQueryString();
        Integer pageSize = esParams.getPageSize();//每页显示条数
        Integer currentPage = esParams.getCurrentPage();//当前第几页
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("blog_article");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.preTags( "<font color='red'>" ).postTags( "</font>" ).field("title").field("summary").field("content");
        long totalSize=0;
        searchSourceBuilder.
                size(pageSize).
                from(currentPage*pageSize).
                query(QueryBuilders.multiMatchQuery(queryStr,"title","summary","content").   //设置多字段
                        fuzziness(Fuzziness.ONE)).                                                      //设置fuzziness为1
                highlighter(highlightBuilder);                                                      //设置高亮

        searchRequest.source(searchSourceBuilder);
        List<Article_model_es> list = new ArrayList<>();
        try {
            SearchResponse searchResponse = null;
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            SearchHit[] hits = searchResponse.getHits().getHits();
            totalSize = searchResponse.getHits().getTotalHits().value;
            if (totalSize > 0) {
                esResult.setTotalSize((int) totalSize);
                SearchHit[] searchHit = hits;
                for (SearchHit hit : searchHit) {
                    String sourceAsString = hit.getSourceAsString();
                    System.out.println("sourceAsString==>"+sourceAsString);
                    Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                    Article_model_es article_model_es = JSON.parseObject(sourceAsString, Article_model_es.class);
                    article_model_es.setId(Long.valueOf(hit.getId()));
                    HighlightField title = highlightFields.get("title");
                    if (title!=null){
                        article_model_es.setTitle(title.getFragments()[0].string());
                    }
                    HighlightField content = highlightFields.get("content");
                    String contentStr=article_model_es.getContent();
                    if (content!=null){
                        //如果有高亮字段则设置高亮字段
                        contentStr=content.getFragments()[0].string();
                    }
                    //剪一下content的长度
                    if (contentStr!=null&&contentStr.length()>256){
                        contentStr=contentStr.substring(0,256);
                    }
                    article_model_es.setContent(contentStr);
                    HighlightField summary = highlightFields.get("summary");
                    if (summary!=null){
                        article_model_es.setSummary(summary.getFragments()[0].string());
                    }
                    list.add(article_model_es);
                }
                esResult.setList(list);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return esResult;
    }


    @Override
    public List<String> findBySuggest(String queryStr){
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("blog_article");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //设置suggest
        searchSourceBuilder.
                size(10).                                                  //给出10条推荐
                suggest(new SuggestBuilder().
                        addSuggestion("blog_suggest",               //设置suggest的名字
                                new CompletionSuggestionBuilder("title.suggest").prefix(queryStr)));     //设置推荐的字段以及搜索的字段
        searchRequest.source(searchSourceBuilder);
        List<String> list = new ArrayList<>();
        try {
            SearchResponse searchResponse = null;
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            Suggest suggest = searchResponse.getSuggest();      //得到suggest
            Suggest.Suggestion
                    <? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>>
                    blog_suggest = suggest.getSuggestion("blog_suggest");
            //获取实体entity
            for (Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> entry : blog_suggest.getEntries()) {
                List<? extends Suggest.Suggestion.Entry.Option> options = entry.getOptions();
                for (Suggest.Suggestion.Entry.Option option : options) {
                    //获取option之后拿到推荐的text即可
                    String text = option.getText().string();
                    list.add(text);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }
}
